<?php

namespace App\Services\YinShangPay\V6;
//被扫
use Illuminate\Support\Collection;

class BCPayService
{
    //被扫操作
    const PayApi = "https://api-mop-wh.open.chinaums.com/v6/poslink/transaction/pay";
//    const PayApi="https://test-api-open.chinaums.com/v4/poslink/transaction/pay";
    const PayQuery = "https://api-mop-wh.open.chinaums.com/v6/poslink/transaction/query";
//    const PayQuery="https://test-api-open.chinaums.com/v2/poslink/transaction/query";
    const RefundQuery = "https://api-mop-wh.open.chinaums.com/v6/poslink/transaction/query-refund";
    const Refund = "https://api-mop-wh.open.chinaums.com/v6/poslink/transaction/refund";
//    const Refund="https://test-api-open.chinaums.com/v2/poslink/transaction/refund";
    const VoidPayment = "https://api-mop-wh.open.chinaums.com/v6/poslink/transaction/voidpayment";
    //主扫操作-获取二维码
    //token
    const AccessToken = "https://api-mop.chinaums.com/v2/token/access";

//    public $appId = "8a81c1bd831e4c960187bcb1aea14a66";
//    public $appKey = "1c3d8aacd8d7479c926486b9deb01633";
//    public $merchantId = "898341286995736";
//    public $terminalCode = "12571667";
//    public $storeId = "2023012914242355846";

    public $appId ;
    public $appKey ;
    public $merchantId ;
    public $terminalCode;
    public $storeId ;

    public function __construct(string $appId, string $appKey, string $merchantId, string $terminalCode, string $storeId)
    {
        $this->appId = $appId;
        $this->appKey = $appKey;
        $this->merchantId = $merchantId;
        $this->terminalCode = $terminalCode;
        $this->storeId = $storeId;
    }

    //被动扫码支付
    public function scanPay(array $param): array
    {
        if (!isset($param["out_trade_no"])) {
            $out_trade_no = date('YmdHis', time()) . substr(microtime(), 2, 6) . sprintf('%03d', rand(0, 9999));
        } else {
            $out_trade_no = $param["out_trade_no"] ?? "";
        }
        $deviceType = "11";
        $data = [
//            "discountCode" => "",
            "merchantCode" => $this->merchantId,//商户号 y
            "terminalCode" => $this->terminalCode,//终端号y
            "transactionAmount" => $param["transactionAmount"] ?? 0,//y  交易金额分
            "transactionCurrencyCode" => $param["transactionCurrencyCode"]??"156",//y 交易币种
            "merchantOrderId" => $out_trade_no,//"",
            "merchantRemark" => $param["merchantRemark"] ?? "",
            "payMode" => $param["payMode"] ?? "CODE_SCAN",
            "payCode" => $param["payCode"] ?? "",//"134524350966727175",//payCode: authCode
//            "goods"=>"json_encode(array([{"goodsId"=>"001","goodsName"=>"鸡蛋","quantity"=>"10","price"=>"1","goodsCategory"=>"food meterial","body"=>"two eggs","discount"=>""}]))",
            "storeId" => $this->storeId,
            "deviceType" => $deviceType,
        ];
        if (isset($param["goods"])) {
            $data["goods"] = $param["goods"];
        }
//        $token = "be25eee236654f0eb71e60476c61f6b5";
//        if (empty($token)) {
//            $token = $this->getAccessToken();
//        }
        $body = json_encode($data);
        $header = [
            'Content-Type: application/json',
            'Authorization: ' . $this->getSign($body)
        ];
//        $header=[
//            'Content-Type: application/json',
//            'Authorization:OPEN-ACCESS-TOKEN AccessToken="'.$token.'",AppId="'.self::AppId.'"'
//        ];
        $res = $this->curl(self::PayApi, 'POST', $body,
            $header);
        return $res;
    }

    public function getAccessToken(): string
    {
        $url = self::AccessToken;
        $params = [
            "appId" => $this->appId,
            "timestamp" => date("YmdHis", time()),
            "nonce" => md5(uniqid(microtime(true), true)),
            "signMethod" => "SHA256",
        ];
        $str = $params['appId'] . $params['timestamp'] . $params['nonce'] . $this->appKey;
        $signature = bin2hex(hash('SHA256', $str, true));
        $params["signature"] = $signature;
        $result = $this->curl($url, 'POST', $params, ['Content-type: application/json']);
        return $result->accessToken ?? "";
    }


    public function getSign($body)
    {
        $timestamp = date("YmdHis", time());
        $nonce = md5(uniqid(microtime(true), true));
        $str = bin2hex(hash('sha256', $body, true));
        $signature = base64_encode(hash_hmac('sha256', $this->appId . "$timestamp$nonce$str", $this->appKey, true));
        $authorization = "OPEN-BODY-SIG AppId=\"" . $this->appId . "\", Timestamp=\"$timestamp\", Nonce=\"$nonce\", Signature=\"$signature\"";
        return $authorization;
    }

    public function query(array $param): array
    {
        $data = [
            "merchantCode" => $this->merchantId,
            "terminalCode" => $this->terminalCode,
            "merchantOrderId" => $param["merchantOrderId"],//"202408091644270689613644",
//            "originalOrderId" => $param["originalOrderId"],// "20240809164424111213823055"
        ];
        $body = json_encode($data);
        $header = [
            'Content-Type: application/json',
            'Authorization: ' . $this->getSign($body)
        ];
//      $header=[
//          'Content-Type: application/json',
//          'Authorization:OPEN-ACCESS-TOKEN AccessToken="'.$token.'",AppId="'.self::AppId.'"'
//      ];
        $res = $this->curl(self::PayQuery, 'POST', $body,
            $header);
        return $res;
    }

    public function refundQuery(array $param): array
    {
        $data = [
            "merchantCode" => $this->merchantId,
            "terminalCode" => $this->terminalCode,
            "merchantOrderId" => $param["merchantOrderId"],//"202408091644270689613644",
            "originalOrderId" => $param["originalOrderId"]??"",//"20240809164424111213823055",
            "refundRequestId" => $param["refundRequestId"] ?? ""
        ];
        $body = json_encode($data);
        $header = [
            'Content-Type: application/json',
            'Authorization: ' . $this->getSign($body)
        ];
//      $header=[
//          'Content-Type: application/json',
//          'Authorization:OPEN-ACCESS-TOKEN AccessToken="'.$token.'",AppId="'.self::AppId.'"'
//      ];
        $res = $this->curl(self::RefundQuery, 'POST', $body,
            $header);
        return $res;
    }

    public function refund(array $param): array
    {
//        'merchantOrderId' => $out_trade_no,
//        'refundRequestId' => $out_trade_no,
        if (!isset($param["refundRequestId"])) {
            $out_trade_no = "R" . date('YmdHis', time()) . substr(microtime(), 2, 6) . sprintf('%03d', rand(0, 9999));
        } else {
            $out_trade_no = $param["refundRequestId"] ?? "";
        }
        $data = [
            "merchantCode" => $this->merchantId,
            "terminalCode" => $this->terminalCode,
            "merchantOrderId"=>$param["merchantOrderId"],
            "refundRequestId" => $out_trade_no,
            "transactionAmount" => $param["transactionAmount"] ?? 0,
            "transactionCurrencyCode" => "156"
        ];
        $body = json_encode($data);
        $header = [
            'Content-Type: application/json',
            'Authorization: ' . $this->getSign($body)
        ];
//      $header=[
//          'Content-Type: application/json',
//          'Authorization:OPEN-ACCESS-TOKEN AccessToken="'.$token.'",AppId="'.self::AppId.'"'
//      ];
        $res = $this->curl(self::Refund, 'POST', $body,
            $header);
        return $res;
    }

    //支付撤销
    public function voidPayment(array $param): array
    {
        if (!isset($param["merchantOrderId"])) {
            $out_trade_no = "R" . date('YmdHis', time()) . substr(microtime(), 2, 6) . sprintf('%03d', rand(0, 9999));
        } else {
            $out_trade_no = $param["merchantOrderId"] ?? "";
        }
        $data = [
            "merchantCode" => $this->merchantId,
            "terminalCode" => $this->terminalCode,
            "merchantOrderId" => $out_trade_no,
//            "originalOrderId" => $param["originalOrderId"] ?? "",
        ];
        $body = json_encode($data);
        $header = [
            'Content-Type: application/json',
            'Authorization: ' . $this->getSign($body)
        ];
//      $header=[
//          'Content-Type: application/json',
//          'Authorization:OPEN-ACCESS-TOKEN AccessToken="'.$token.'",AppId="'.self::AppId.'"'
//      ];
        $res = $this->curl(self::VoidPayment, 'POST', $body,
            $header);
        return $res;
    }


    public function curl($url, $method, $params, $header = [])
    {
        //初始化CURL句柄
        $curl = curl_init();

        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($header)) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        }
        //请求时间
        $timeout = 30;
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
        switch ($method) {
            case "GET" :
                curl_setopt($curl, CURLOPT_HTTPGET, true);
                break;
            case "POST":
                if (is_array($params)) {
                    $params = json_encode($params, 320);
                }
                curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
                curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
                break;
        }
        $data = curl_exec($curl);
        $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        curl_close($curl);//关闭cURL会话

        return json_decode($data, true);
    }

}

